#include "Actor.h"
#include "xwpch.h"
#include <gtc/matrix_transform.hpp>
#include "Core/Application.h"

Actor::Actor()
{
	Parent = nullptr;
	Root = this;
	Location = glm::vec3(0.0f, 0.0f, 0.0f);
	Scale = glm::vec3(1.0f);
	MovementSpeed = 15.0f;

	WorldUp = glm::vec3(0.0f, 1.0f, 0.0f);
	Forward = glm::vec3(0.0f, 0.0f, 1.0f);
	Right = glm::normalize(glm::cross(Forward, WorldUp));  // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
	Up = glm::normalize(glm::cross(Right, Forward));
	Velocity = glm::vec3(0.0f);

	RotationAxis = glm::vec3(0.0f, 1.0f, 0.0f);

	T = glm::mat4(1.0f);
	R = glm::mat4(1.0f);
	M = glm::mat4(1.0f);
	S = glm::mat4(1.0f);
}

Actor::~Actor()
{
	Destroyed();
}

void Actor::BeginPlay()
{
	for (auto actor : Children)
	{
		actor->BeginPlay();
	}
}

void Actor::Tick(double DetaTime)
{
	for (auto actor : Children)
	{
		actor->Tick(DetaTime);
	}
}

void Actor::Destroyed()
{
	for (auto actor : Children)
	{
		delete actor;
	}
}

void Actor::RenderActor()
{
	for (auto actor : Children)
	{
		actor->RenderActor();
	}
}

void Actor::SetActorLocation(glm::vec3 NewLocation)
{
	Location = NewLocation;
}

void Actor::SetActorAngle(float angle)
{
	Angle = angle;
}

void Actor::SetActorScale(glm::vec3 NewScale)
{
	Scale = NewScale;
}

void Actor::SetActorForward(glm::vec3 NewForward)
{
	Forward = NewForward;
}

void Actor::SetActorRotation(const FRotator& NewRotator)
{
	Rotation = NewRotator;
}

void Actor::SetupAttachment(Actor* AttachToParent)
{
	SetRoot(AttachToParent);
	SetParent(AttachToParent);
	AttachToParent->AddToChildren(this);
	Target = &AttachToParent->Location;
}

void Actor::UpdateChildLocation(glm::vec3 DetalLocation)
{
	Location += DetalLocation;

	for (auto actor : Children)
	{
		actor->UpdateChildLocation(DetalLocation);
	}
}

void Actor::AddActorLocalRotation(const FRotator& DeltaRotation)
{
	Rotation += DeltaRotation;
}

void Actor::RecalculateTranformMatrix()
{

}

glm::mat4 Actor::GetTransformMatrix()
{
	T = glm::translate(glm::mat4(1.0f), Location);

	R = Rotation.RotationMatrix();

	S = glm::scale(glm::mat4(1.0f), Scale);

	if (Parent)
	{
		M = Parent->GetTransformMatrix() * T * R * S;
	}
	else
	{
		M = T * R * S;
	}

	return M;
}

void Actor::SetRoot(Actor* root)
{
	Root = root->Root;
}

void Actor::SetParent(Actor* parent)
{
	Parent = parent;
}

void Actor::OnEvent(double DetaTime)
{

}

void Actor::OnMouse(double xpos, double ypos)
{

}

glm::vec3 Actor::GetForward2D()
{
	return glm::normalize(glm::vec3(Forward.x, 0, Forward.z));
}

glm::vec3 Actor::GetRight2D()
{
	return glm::normalize(glm::vec3(Right.x, 0, Right.z));
}

void Actor::AddToChildren(Actor* Child)
{
	Children.push_back(Child);
}